package com.entity.NeuralNetworks;

import com.util.Function.Function;

import java.math.BigInteger;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;

/**
 * Created by wlc on 2018/5/16.
 */
public class Neurons {
    /**
     * 数据成员
     */
    private BigInteger id;

    private HashMap<BigInteger,Double> inputWeights;  //与该神经元相连的输入神经元[ID,权值]
    private HashMap<BigInteger,Double> inputValues;   //与该神经元相连的输入神经元[ID,输入值*权值]，或纯输入
    private HashMap<BigInteger,Double> inputDeviation; //与该神经元相连的输出神经元[ID,总偏差*权值]

    private ArrayList<BigInteger> outputNeurons;     //与该神经元相连的输出神经元ID
    private Double outputValue;                  //该神经元的纯输出值

    private Function activationFunction;        //该神经元的激活函数
    private Double threshold;                    //该神经元的阈值
    private Double totalDeviation;            //该神经元的总偏差

    public Neurons(){
        inputWeights = new HashMap<>();
        inputValues = new HashMap<>();
        inputDeviation = new HashMap<>();

        outputNeurons = new ArrayList<>();
        outputValue = 0d;

        threshold = 0d;
        totalDeviation = 0d;
    }

    /**
     *数据成员设置和获取函数
     */
    public void setId(BigInteger id){
        this.id = id;
    }

    public BigInteger getId(){
        return this.id;
    }

    public void setInputWeights(BigInteger id,Double weight){
        this.inputWeights.put(id,weight);

    }

    public HashMap<BigInteger,Double> getInputWeights(){
        return this.inputWeights;
    }

    public void setInputValues(BigInteger id,Double inputValue){
        this.inputValues.put(id,inputValue);
    }

    public HashMap<BigInteger,Double> getInputValues(){
        return this.inputValues;
    }

    public void setInputDeviation(BigInteger id,Double deviation){
        this.inputDeviation.put(id,deviation);
    }

    public HashMap<BigInteger,Double> getInputDeviation(){
        return this.inputDeviation;
    }

    public void setOutputs(BigInteger neuronsId){
        this.outputNeurons.add(neuronsId);
    }

    public ArrayList<BigInteger> getOutputs(){
        return this.outputNeurons;
    }

    public void setOutputValue(Double outputValue){
        this.outputValue = outputValue;
    }

    public Double getOutputValue(){
        return this.outputValue;
    }

    public void setActivationFunction(Function function){
        this.activationFunction = function;
    }

    public Function getActivationFunction(){
        return this.activationFunction;
    }

    public void  setThreshold(Double threshold){
        this.threshold = threshold;
    } //阈值初始化

    public Double getThreshold(){
        return this.threshold;
    }

    public void setTotalDeviation(Double totalDeviation){
        this.totalDeviation = totalDeviation;
    }

    public Double getTotalDeviation(){
        return this.totalDeviation;
    }


    /**
     * y = f(x-d) : 根据输入，阈值，激活函数计算输出
     */
    public void computeOutput(){
        Double x = 0d;
        Iterator iterator = this.inputValues.entrySet().iterator();
        while (iterator.hasNext()){
            Map.Entry entry = (Map.Entry) iterator.next();
            x += (Double) entry.getValue();
        }
        this.outputValue = activationFunction.activation(x - this.threshold);
    }

    /**
     * 根据总偏差来计算每一突触上的偏差
     */
    public void computeDeviation(){
        Iterator iterator = this.inputWeights.entrySet().iterator();
        while (iterator.hasNext()){
            Map.Entry entry = (Map.Entry) iterator.next();
            BigInteger id = (BigInteger) entry.getKey();
            Double weight = (Double) entry.getValue();
            this.inputDeviation.put(id,weight * this.totalDeviation);
        }
    }
}
